package org.dhis2.form.model

import org.dhis2.form.ui.event.RecyclerViewUiEvents
import org.dhis2.form.ui.event.UiEventFactory
import org.dhis2.form.ui.intent.FormIntent
import org.dhis2.form.ui.style.FormUiModelStyle
import org.hisp.dhis.android.core.common.ValueType

data class FieldUiModelImpl(
    override val uid: String,
    override val layoutId: Int,
    override val value: String? = null,
    override val focused: Boolean = false,
    override val error: String? = null,
    override val editable: Boolean = true,
    override val warning: String? = null,
    override val mandatory: Boolean = false,
    override val label: String,
    override val programStageSection: String? = null,
    override val style: FormUiModelStyle? = null,
    override val hint: String? = null,
    override val description: String? = null,
    override val valueType: ValueType,
    override val legend: LegendValue? = null,
    override val optionSet: String? = null,
    override val allowFutureDates: Boolean? = null,
    override val uiEventFactory: UiEventFactory? = null,
    override val displayName: String? = null
) : FieldUiModel {

    private var callback: FieldUiModel.Callback? = null

    override val formattedLabel: String
        get() = if (mandatory) "$label *" else label

    override fun setCallback(callback: FieldUiModel.Callback) {
        this.callback = callback
    }

    override fun onItemClick() {
        callback?.intent(FormIntent.OnFocus(uid, value))
    }

    override fun onNext() {
        callback?.intent(FormIntent.OnNext(uid, value))
    }

    override fun onTextChange(value: String?) {
        callback?.intent(FormIntent.OnTextChange(uid, value))
    }

    override fun onDescriptionClick() {
        callback?.recyclerViewUiEvents(
            RecyclerViewUiEvents.ShowDescriptionLabelDialog(
                label,
                description
            )
        )
    }

    override fun onClear() {
        onItemClick()
        callback?.intent(FormIntent.ClearValue(uid))
    }

    override fun invokeUiEvent() {
        onItemClick()
        uiEventFactory?.generateEvent(value)?.let {
            callback?.recyclerViewUiEvents(it)
        }
    }

    override fun setValue(value: String?) = this.copy(value = value)

    override fun setDisplayName(displayName: String?) = this.copy(displayName = displayName)

    override fun setFocus() = this.copy(focused = true)

    override fun setError(error: String?) = this.copy(error = error)

    override fun setEditable(editable: Boolean) = this.copy(editable = editable)

    override fun setLegend(legendValue: LegendValue?) = this.copy(legend = legend)

    override fun setWarning(warning: String) = this.copy(warning = warning)

    override fun setFieldMandatory() = this.copy(mandatory = true)

    override fun equals(item: FieldUiModel): Boolean {
        if (this === item) return true
        if (javaClass != item.javaClass) return false

        item as FieldUiModelImpl

        if (uid != item.uid) return false
        if (layoutId != item.layoutId) return false
        if (value != item.value) return false
        if (focused != item.focused) return false
        if (error != item.error) return false
        if (editable != item.editable) return false
        if (warning != item.warning) return false
        if (mandatory != item.mandatory) return false
        if (label != item.label) return false
        if (programStageSection != item.programStageSection) return false
        if (style != item.style) return false
        if (hint != item.hint) return false
        if (description != item.description) return false
        if (valueType != item.valueType) return false
        if (legend != item.legend) return false
        if (optionSet != item.optionSet) return false
        if (allowFutureDates != item.allowFutureDates) return false
        if (callback != item.callback) return false

        return true
    }
}
